#ifndef SIPUSERAGENT_HPP__
#define SIPUSERAGENT_HPP__

#include "WTResipDll/SipWTResipDllItf.hpp"
#include "WTResipDll/SipWtsipUtils.hpp"
#include "WTResipDll/SipDialogSet.hpp"
//#include "SipDialogSet.hpp"

#include "resip/stack/TransactionUser.hxx"
#include "resip/stack/SipStack.hxx"
#include "resip/stack/SelectInterruptor.hxx"
#include "resip/stack/InterruptableStackThread.hxx"
#include "rutil/ThreadIf.hxx"


namespace wtsip{

class CSipDialogSet;
class CSipRealPlayAdaptor;
class CSipKeepAliveAdaptor;
class CSipDevInfoSession;
class CSipDlgSetHandle;
class CSipUserAgent;
class CSipSrvTransaction;
class CSipDialogBase;
class CSipInviteDialog;
class CSipRegistration;
class CSipSubscription;
class CSipClnTransaction;

class resip::SipStack;
class resip::SipStackOptions;
class resip::SelectInterruptor;
class resip::InterruptableStackThread;

class RESIP_PUBLIC CSipUserAgent: public resip::TransactionUser, public resip::ThreadIf
{
public:
    CSipUserAgent();
    
    virtual ~CSipUserAgent();    

    virtual void thread();

    virtual void shutdown();

    bool init(const resip::TransportType type, const SUri& localContact);

    bool setAgentVersion(const std::string& agent);

    CSipDialogSet& getDialogSet();

    const SUri& getLocalContact() const;

    //////////////////////  Create Request/Response ////////////////////////

    CapSipMessage createRequest(const SUri& tar, const SUri& from, const SUri& to, 
        wtsip::EMethodTypes mth, bool computeId=false);

    bool cancel(const resip::Data& id);

    CapSipMessage createResponse(CSipMessage& msg, const ESipCodeType cType, const std::string& reason);

    //////////////// Create Dialog /////////////////////

    ISipDialogBase* createDialog(const SUri& local, const SUri& remote);

    ISipDialogBase* createDialog(ISipSrvTransaction& srv, CSipMessage& msg);

    ////////////// Transaction Methods ////////////////////

    ISipClnTransaction* createClnTransaction(CSipMessage& msg);

    ISipSrvTransaction* createSrvTransaction(CSipMessage& msg);

    bool destroyClientTran(const resip::Data& tid);

    bool destroyServerTran(const resip::Data& tid);

    CSipClnTransaction* matchClnTransaction(CSipMessage& msg);

    CSipSrvTransaction* matchSrvTransaction(CSipMessage& msg);

    ISipClnTransaction* findClnTransaction(CSipMessage& msg);

    ISipSrvTransaction* findSrvTransaction(CSipMessage& msg);

    ////////////////////

    bool send(CapSipMessage msg);

	//bool postTimerMessage(ApplicationMessage* msg, int seconds);

    //bool postSelfMessage(TransactionMessage* msg);

    bool dispatch(CapSipMessage msg);

    //////////////////////////// register methods /////////////////////////

    bool registerListener(ISipUserAgentListener* ls);

    bool unregisterListener(ISipUserAgentListener* ls);

    bool registerDlgSetHandler(IDialogSetHandle* dh);

    bool unregisterDlgSetHandler(IDialogSetHandle* dh);

    //virtual bool onProcess(SipMessage* msg);

    //virtual bool enableProcess();

    virtual const resip::Data& name() const;

private:
    
    bool m_shuttingDown;

    resip::Data m_AgentVer;

    resip::TransportType m_transport;
    
    CSipDialogSet m_DialogSet;

    ISipUserAgentListener* m_uaListener;

    std::map<resip::Data, CSipSrvTransaction*> m_srvTransations;

    std::map<resip::Data, CSipClnTransaction*> m_clnTransations;

    resip::Mutex m_srvMutex;

    resip::Mutex m_clnMutex;

    resip::SipStack* m_Stack;

    resip::SipStackOptions* m_StackOptions;

    resip::SelectInterruptor* m_SelectInterruptor;

    resip::InterruptableStackThread* m_StackThread;

    SUri m_localContact;
};

}



#endif
